﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using RSSFeedReader.Commands;
using RSSFeedReader.Data.Models;
using RSSFeedReader.Resources;
using RSSFeedReader.Services;

namespace RSSFeedReader.ViewModels
{
    /// <summary>
    /// Class to add a new feed to the <see cref="RSSFeedReader.Data.Models.ChannelDataSource"/>.
    /// </summary>
    public class AddNewFeedViewModel : ViewModelBase, IDataErrorInfo
    {
        #region Fields

        DelegateCommand _addNewFeedCommand;
        DelegateCommand _autoPasteUrlCommand;

        string _feedUrl;
        string _clipboardText;

        #endregion

        #region Constructor

        /// <summary>
        /// Initialize a new instance of the <see cref="RSSFeedReader.ViewModels.AddNewFeedViewModel"/> class.
        /// </summary>
        public AddNewFeedViewModel()
        {
        }

        #endregion

        #region Commands

        #region AddNewFeedCommand
        /// <summary>
        /// AddNewFeedCommand adds a new feed.
        /// </summary>
        public ICommand AddNewFeedCommand
        {
            get
            {
                if (_addNewFeedCommand == null)
                    _addNewFeedCommand = new DelegateCommand(DoAddNewFeedCommand, CanDoAddNewFeedCommand);

                return _addNewFeedCommand;
            }
        }

        /// <summary>
        /// Logic to determine if the AddNewFeedCommand can be executed.
        /// </summary>
        /// <returns>True if the AddNewFeedCommand can be executed.</returns>
        bool CanDoAddNewFeedCommand()
        {
            return !string.IsNullOrEmpty(_feedUrl) && ChannelDataSource.Instance.IsValidUrl(_feedUrl);
        }

        /// <summary>
        /// Adds the feed to the <see cref="RSSFeedReader.Data.Models.ChannelDataSource"/> instance.
        /// </summary>
        void DoAddNewFeedCommand()
        {
            if (IsNewFeed())
            {
                ChannelDataSource.Instance.AddChannel(FeedUrl);
                OnRequestClose();
            }
            else
            {
                DisplayMessage.ShowMessage("The feed all ready exists", Strings.ApplicationName,
                    System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
            }
        } 
        #endregion

        #region AutoPasteUrlCommand
        /// <summary>
        /// Auto paste the url in the clipboard if valid.
        /// </summary>
        public ICommand AutoPasteUrlCommand
        {
            get
            {
                if (_autoPasteUrlCommand == null)
                    _autoPasteUrlCommand = new DelegateCommand(DoAutoPasteUrlCommand, CanAutoPasteUrlCommand);

                return _autoPasteUrlCommand;
            }
        }

        /// <summary>
        /// Checks if there is text data in the clipboard and if it is a valid url.
        /// </summary>
        /// <returns>True if the AutoPasteUrlCommand can be executed.</returns>
        bool CanAutoPasteUrlCommand()
        {
            _clipboardText = Clipboard.GetText().Trim();
            return !string.IsNullOrEmpty(_clipboardText) && ChannelDataSource.Instance.IsValidUrl(_clipboardText)
                && string.IsNullOrEmpty(FeedUrl);
        }

        /// <summary>
        /// Executes the AutoPasteUrlCommand.
        /// </summary>
        void DoAutoPasteUrlCommand()
        {
            FeedUrl = _clipboardText;
        }
        #endregion

        #endregion
        
        #region Public Properties

        /// <summary>
        /// Gets or sets the url to add.
        /// </summary>
        public string FeedUrl
        {
            get { return _feedUrl; }
            set
            {
                if (_feedUrl == value)
                    return;

                _feedUrl = value;
                OnPropertyChanged("FeedUrl");
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Gets the validation error for the specified property.
        /// </summary>
        /// <param name="propertyName">The property being validated.</param>
        /// <returns>The error message if validation fails, or null if validation is passed.</returns>
        string GetValidationError(string propertyName)
        {
            if (propertyName != "FeedUrl")
                return null;

            string error = null;

            switch (propertyName)
            {
                case "FeedUrl":
                    error = ValidateUrl();
                    break;

                default:
                    Debug.Fail("Unexpected property being validated on feed: " + propertyName);
                    break;
            }

            Debug.WriteLineIf(error != null, string.Format("Validation on url feed error = {0}", error));
            return error;
        }

        /// <summary>
        /// Validates the url being added.
        /// </summary>
        /// <returns>The error message, or null if url was validated successfully.</returns>
        string ValidateUrl()
        {
            if (string.IsNullOrEmpty(FeedUrl))
                return Strings.Channel_Url_IsMissing;

            if (!ChannelDataSource.Instance.IsValidUrl(FeedUrl))
                return Strings.Channel_Url_Invalid;

            return null;
        }

        /// <summary>
        /// Gets a value indicating if the feed being added all ready exists
        /// in the <see cref="RSSFeedReader.Data.Models.ChannelDataSource"/> instance.
        /// </summary>
        /// <returns></returns>
        bool IsNewFeed()
        {
            return !ChannelDataSource.Instance.ContainsChannel(_feedUrl);
        }

        #endregion

        #region IDataErrorInfo Members

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        string IDataErrorInfo.Error
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <param name="propertyName">The name of the property whose error message to get.</param>
        /// <returns>The error message for the property.</returns>
        string IDataErrorInfo.this[string propertyName]
        {
            get { return GetValidationError(propertyName); }
        }

        #endregion
    }
}
